<?php
namespace Home\Controller;

use Utuo\DistributionShopForeground;
use My\Model\DistributionShopOrderModel;
use My\Model\DistributionShopRedPacketModel;
use Home\Logic\DistributionShopRedPacketLogic;
use Home\Logic\DistributionShopPayLogic;
use My\Model\WechatUserModel;
use My\Model\UserRole;
use Utuo\DistributionShopScore;
use Utuo\SystemInfo;

class DisShopPayController extends DistributionShopForeground {
	
	public function _init() {
		layout('disshop');
		$this->setModelName("DistributionShop");
		$this->setModelControllerName("DisShop");
		if ( in_array(ACTION_NAME, array('notify', 'pay', 'notifyInvite')) ) { // 排除不验证登录的动作
			$this->setCheckLogin(false);
		}
	}
	
	/**
	 * 选择支付方式与银行
	 */
	public function indexAction() {
		$orderId = I("id", 0);
		// 获得订单
		$m = M("DistributionShopOrder");
		$orderId and $order = $m->where("id=%d", $orderId)->find($orderId);
		// 获得接口列表
		$produtPayApiLists = $this->getPayApiList();
		if ( $order['support_cod'] ) {
			$produtPayApiLists = array_merge($produtPayApiLists, array('COD' =>"货到付款"));
		}
		$this->assign("order", $order);
		$this->assign("productPayApiJSON", json_encode($produtPayApiLists));
		$this->display("{$this->modelControllerName}/payIndex");
	}
	
	/**
	 * 转入支付接口
	 * @param payVo $vo 订单数据
	 */
	public function toPayAction() {
		$orderId = I("id", 0);
		$apitype = I('apitype', ''); // 获得支付方式
		$apiConfig = $this->getApiConfig(array('paymentMethod' => $apitype));
		// 获得订单
		if ( $orderId ) {
			$this->rwSeparate(0);
			$order = D( "My/DistributionShopOrder" )->getOrder($orderId) or $this->error("订单无效($orderId)!");
			$this->rwSeparate(1);
		}
		$backUrl = $this->getBackUrl($order);
		// 检查重复支付
		if( $order['pay_status'] ) {
			$this->error("已经付过款了。", $backUrl); exit();
		}
		// 0元订单处理
		if ( $order['actual_cost']*1 <= 0 ) {
			$this->paySuccess($order['order_id'], $apitype);
			$this->success("准备收货吧。", $backUrl); exit();
		}
		// 处理结算方式
		if($apitype == "COD") {
			M("DistributionShopOrder")->where("id=%d", $orderId)
									->save( array( "order_status" => \My\Model\ProductOrderModel::ORDER_STATUS_SHIPPING, 
											"pay_method" => $apitype,
											"confirm_time" => time(),
									) );
			$this->success("准备收货吧。", $backUrl); exit();
		} elseif(empty($apitype) or empty($apiConfig)) {
			$this->error("请选择结算方式。"); exit();
		}
		$vo = $this->parseOrder( $order );
		// 支付接口附加参数
		$apiConfig['wparam'] = array_merge($apiConfig['wparam'], array(
			'backUrl' => $backUrl, // 支付成功后的返回页面
		));
		// 获得支付接口
		$pay = \Utuo\Pay::getInstance($apitype, $apiConfig);
		// 生成支付表单
		$formHtml = $pay->buildRequestForm($vo);
		if ( IS_AJAX ) {
			$this->success("", "", array('payForm'=>$formHtml)); exit();
		} else {
			header("Content-Type:text/html;charset=utf-8");
			exit( $formHtml );
		}
	}
	
	/**
	 * 通知回调连接
	 */
	public function notifyAction() {
		$apitype = I('get.apitype', ''); // 获得支付方式
		$pay = \Utuo\Pay::getInstance($apitype, $this->getApiConfig(array('paymentMethod' => $apitype)));
		switch ($apitype) {
			case "Tenpay":
				$paramNames = "sign_type,service_version,input_charset,sign,sign_key_index,trade_mode,trade_state,pay_info,partner,bank_type,bank_billno,total_fee,fee_type,notify_id,transaction_id,out_trade_no,attach,time_end,transport_fee,product_fee,discount,buyer_alias";
				foreach(explode(",", $paramNames) as $v) {
					$notify[$v] = $_REQUEST[$v];
				}
				if( $pay->verifyNotify($notify) ) {
					$this->paySuccess($notify["out_trade_no"], $apitype);
				}
				exit();
			case "WxTenpay":
				if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
					// 处理数据
					$notify = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);
					if( $pay->verifyNotify($notify) ) {
						$this->paySuccess($notify["out_trade_no"], $apitype);
						exit("<xml><return_code>SUCCESS</return_code></xml>");
					}
				} else {
					exit("<xml><return_code>FAIL</return_code></xml>");
				}
			default:
				exit("<xml><return_code>FAIL</return_code></xml>");
		}
	}
	
	/**
	 * 选择的商品的金额
	 * @param unknown $order
	 * @param unknown $orderGoodsIds
	 */
	private function getSelectedGoodsFee( $order, $orderGoodsIds ) {
		if ( $orderGoodsIds === true ) { // 全款
			return $order['goods_amount'];
		}
		// 退款申请详情
		$total = 0.00;
		foreach ( $order['orderItems'] as $productId => $product ) {
			foreach ( $product['items'] as $v ) {
				if ( in_array($v['orderGoodsId'], $orderGoodsIds) ) {
					$total+=$v['productNumber']*$v['productPrice'];
				}
			}
		}
		return $total;
	}
	
	/**
	 * 申请订单退款
	 */
	public function refundAction() {
		$orderId = I("id", 0);
		$selectedOrderGoodsIds = I("goods", true) or $this->responseMsg("未选择退款商品");
		// 获得订单
		if ( $orderId ) {
			$order = D( "My/DistributionShopOrder" )->getOrder($orderId) or $this->responseMsg("订单未找到");
			$refundGoodsFee = $this->getSelectedGoodsFee($order, $selectedOrderGoodsIds);
			if ( !$refundGoodsFee ) {
				$this->responseMsg("订单已没有可退的金额");
			}
			if ( !in_array('refund', $order['operates']) ) {
				$this->responseMsg("当前订单不支持退款");
			} else {
				$allGoods = ($refundGoodsFee == $order['goods_amount']);
				if ( $allGoods ) { // 全款
					if ( !$order['refund_times'] ) { // 第一次全款
						if (false !== M("DistributionShopOrder")->where(array(
									'id' => $order['id'],
									'pay_status' => DistributionShopOrderModel::PAY_STATUS_PAID,
							))->save(array(
									'order_status' => DistributionShopOrderModel::ORDER_STATUS_REFUND_APPLY,
									'refund_times' => array('exp', "refund_times+1"),
									'refund_status' => 1))
						) {
							// 退款申请
							$refundId = M("DistributionShopRefund")->add(array(
									'cid' => $order['cid'],
									'refundNo' => DistributionShopOrderModel::randRefundNo($order['cid']),
									'orderNo' => $order['order_id'],
									'refundTotalFee' => $order['actual_cost'],
									'createTime' => time(),
									'all' => 1,
									'status' => 0,
							));
							
							// 退款申请详情
							foreach ( $order['orderItems'] as $productId => $product ) {
								foreach ( $product['items'] as $v ) {
									$refundGoods[] = array(
										'cid' => $order['cid'],
										'refundId' => $refundId,
										'orderGoodsId' => $v['orderGoodsId'],
										'refundFee' => $v['productNumber']*$v['productPrice'],
									);
								}
							}
							false !== M("DistributionShopRefundGoods")->addAll($refundGoods) and $this->responseMsg("退款申请成功");
							$this->responseMsg(json_encode($refundGoods));
						}
					} else {
						$this->responseMsg("已申请过退全款{$order['refund_times']}次");
					}				
				} else {
					$this->responseMsg("非全款处理");
					// 非全款处理
					//......
				}
			}
			$this->responseMsg("退款申请失败");
		} else {
			$this->responseMsg("订单未找到");
		} 
	}
	
	/**
	 * 退款订单信息查询
	 */
	public function refundSearchAction() {
		$orderId = I("id", 0); // 订单id
		$outRefundNo = I("outRefundNo", null); // 退款No
		// 获得订单
		if ( $orderId ) {
			$this->rwSeparate(0);
			$order = D( "My/DistributionShopOrder" )->getOrder($orderId) or $this->error("订单无效($orderId)!");
			$this->rwSeparate(1);
			$apitype = $order['pay_method'];
		}
		if ( $apitype and $apitype != "COD" ) {
			$pay = \Utuo\Pay::getInstance($apitype, $this->getApiConfig(array('paymentMethod' => $apitype)));
			$refundItem = $pay->refundSearch(null, array(
				'outRefundNo' => $outRefundNo,
				'orderNo' => $order['order_id'],
			)); // 查询订单所有退款信息
			foreach ( $refundItem['list'] as $outRefundNo => $refund ) {
				DistributionShopPayLogic::refundCallBack($outRefundNo, $refund);
			}
		} else {
			$refundItem = false;
		}
		$refundItem and $this->ajaxSuccess("查询成功", array('refund' => $refundItem, 'count' => count($refundItem)));
		$this->ajaxError("查询失败".$order['order_id']);
	}
	
	/**
	 * 支付后的返回页面
	 * @param unknown $cfg
	 * @return Ambigous <string, mixed>
	 */
	protected function getBackUrl( $order ) {
		return U("DisShopOrder/showOrder", "id=".$order['id']."&sid=".$this->sid);
	}
	
	/**
	 * 转化为可提交的订单格式
	 * @param unknown $order
	 */
	protected function parseOrder($order) {
		$vo = new \Utuo\Pay\PayVo;
		$vo->setOrderNo($order['order_id']);
		$vo->setFee($order['actual_cost']);
		$body = "";
		foreach ( $order['orderItems'] as $productId => $product  ) {
			$body.= $product['productName']." ";
		}
		$vo->setBody( mb_substr($body, 0, 20, 'utf8' ) );
		$vo->setTitle("NO:".$order['order_id']);
		return $vo;
	}
	
	/**
	 * 支付成功时
	 * @param unknown $orderId
	 * @param unknown $apitype
	 */
	protected function paySuccess($orderId, $apitype) {
		$this->rwSeparate(0);
		$productOrder = M("DistributionShopOrder")->where("order_id='%s'", $orderId)->find();
		$this->rwSeparate(1);
		$user = M("WechatUser")->find( $productOrder['uid'] ); // 买家
		
		if ( $productOrder['pay_status'] == \My\Model\ProductOrderModel::PAY_STATUS_NOT_PAID ) {
			
		    $saveData  = array(
							"pay_time" => time(),
							"order_status" => \My\Model\ProductOrderModel::ORDER_STATUS_SHIPPING,
							"pay_method" => $apitype,
							"pay_status" => \My\Model\ProductOrderModel::PAY_STATUS_PAID,
						);
		    
		    /* 应用积分 */
		    if ( $productOrder['currency_tmp'] ) {
		        $currencyTmp = unserialize( $productOrder['currency_tmp'] );
		        $saveData['currency_offset'] = empty($currencyTmp['currency_offset']) ? 0 : $currencyTmp['currency_offset'];
		        $saveData['currency_rmb'] = empty($currencyTmp['currency_rmb']) ? 0 : $currencyTmp['currency_rmb'];
		        $saveData['actual_reward_currency'] = empty($currencyTmp['actual_reward_currency']) ? 0 : $currencyTmp['actual_reward_currency']; // 实际应返积分
		        if ( $saveData['currency_offset'] ) {
		            $scoreHandle = DistributionShopScore::getInstance("ScoreTrade", array('cid'=>$productOrder['cid'], 'uid' => $productOrder['uid']));
		            $scoreHandle->exec(array('score'=>0-$saveData['currency_offset']));
		        }
		    }
		    
			/* 支付状态更新 */
			M("DistributionShopOrder")->where("id=%d", $productOrder['id'])->save( $saveData );
			
			/* 购买方式处理 */
			if( $productOrder['buy_method'] == DistributionShopOrderModel::BUY_METHOD_GIFTS ) { // 送礼订单
				M("DistributionShopGifts")->where(array(
												'uid'=>$this->uid, 
												'order_id'=>$productOrder['id']
											))->setField('buy_status', DistributionShopOrderModel::ORDER_GIFTS_STATUS_SHARING); // 设置订单待分享
				
			} elseif ( $productOrder['buy_method'] == DistributionShopOrderModel::BUY_METHOD_TRY ) { // 试用订单
				/* 试用次数更新 */
				M("DistributionShopTry")->where(array(
					'orderId' => $productOrder['id']
				))->save(array(
					'times' => array("exp", "times+1"), // 成功次数加一
					'status' => 0, // 开启下一轮试用
					'orderId' => '',
				));
				
				/* 给买家发红包 */
				$newRedPacket = array();
				for ( $i = 0; $i < 4; $i++ ) {
					$newRedPacket[] = DistributionShopRedPacketLogic::newRedPacket($productOrder['cid'], $productOrder['uid'], 10.00, 150.00, 'TRY_ACTIVE');
				}
				for ( $i = 0; $i < 4; $i++ ) {
					$newRedPacket[] = DistributionShopRedPacketLogic::newRedPacket($productOrder['cid'], $productOrder['uid'], 5.00, 100.00, 'TRY_ACTIVE');
				}
				if ( false !== DistributionShopRedPacketLogic::addRedPacket( $newRedPacket ) ) {
					/* 给买家发送获得红包消息 */
					$data = array(
							"articles" => array(
									array(
											'title' => '购买成功通知',
											'description' => "恭喜您购买成功，并获得60元红包，可以在购买商品时冲抵现金。\n\n",
											'url' => U('DisShopRedPakcet/list', array( 'sid' => $productOrder['cid'], 'type' => 1 ), false, true),
									)
							)
					);
					$this->sendServerMsg($user['openId'], $data, 5);
				}
			}
			
			/* 更新用户销费总金额 */
			$m = M("WechatUser");
			$wechatUser = $m->where("id=%d", $productOrder['uid'])->find();
			$sellsCost = $wechatUser['sellsCost'] + $productOrder['goods_amount'];
			$saveData = array(
				'sellsCost' => $sellsCost,
			);
			/* 自动成为金牌会员 */
			$userRole = new UserRole();
			if ( $userRole->type($wechatUser['type'])->isNot(WechatUserModel::USER_TYPE_FRANCHISED_DEALER) and 
			     $sellsCost != 0 and $sellsCost >= $this->config['dealer_min_sells'] ) {
				$saveData['type'] = $userRole->becomeTo(WechatUserModel::USER_TYPE_FRANCHISED_DEALER)->getType();
				$saveData['dealerTime'] = time();
				/* 更新上级累计推广金牌会员数 */
				if ( $wechatUser['mid'] ) {
				    $m->where("id=%d", $wechatUser['mid'])->save(array(
				        'sonDealerCount' => array('exp', 'sonDealerCount+1'),
				    ));
				}
				if ( !M("Dealer")->add(array(
				    'wechat_uid' => $user['id'],
				    'cid' => $this->cid,
				    'name' => $user['nickname']?$user['nickname']:"",
				    'contacts' => '',
				    'tel' => '',
				    'begin_time' => time(),
				    'end_time' => strtotime("+5 year"),
				    'level' => 0,
				    'status' => 1,
				    'is_deleted' => 0,
				)) ) {
				    SystemInfo::log("insert_dealer_error", M()->getLastSql());
				}
			}
			$m->where("id=%d", $productOrder['uid'])->save($saveData);
			
			/* 更新红包使用 */
			if ( $productOrder['red_packet_id'] ) {
				M("DistributionShopRedPacket")->where('id=%d', $productOrder['red_packet_id'])->setField('efficacy', DistributionShopRedPacketModel::EFFICACYS_USED);
			}
			
			/* 代理分销发送消息提醒 */
			if ( !empty($productOrder['reward_aids']) ) {
			    $agentBonus = array_combine(explode(',', $productOrder['reward_aids']), explode(',', $productOrder['reward_bonus_agent']));
			    foreach ( $agentBonus as $aid => $v ) {
			        $aid == 's' and $aid = 0;
			        if ( $aid ) {
			            $tmpAgent = M("Agent")->where("id=%d", $aid)->find();
			            if ( $tmpAgent ) {
			                $tmpUser = M("WechatUser")->where("id=%d", $tmpAgent['wechat_uid'])->find();
			                if ( $tmpUser ) {
			                    /* 发送支付成功消息 */
			                    $this->sendServerMsg($tmpUser['openId'], array(
			                        'content' => '您分销的订单'.$orderId."买家:{$wechatUser['nickname']}已支付,预计买家确认收货后您将获得￥{$v}元分成",
			                    ));
			                }
			            }
			        }
			    }
			}
		}
	}
	
	/**
	 * 获得支付接口列表
	 * @return multitype:
	 */
	protected function getPayApiList() {
		$d = D("My/ProductPayApi");
		$produtPayApiLists = $d->where("cid=%d and status=1", $this->sid)->getField("tag,name") or $produtPayApiLists = array(); // 获得商家设置的支付接口
		return $produtPayApiLists;
	}
	
	/**
	 * 获得接口配置
	 * @param unknown $cid
	 * @param unknown $cfg
	 * array(
	 * 	'paymentMethod', // 支付方式(*): Alipay,WxTenpay
	 * )
	 * @return array
	 */
	protected function getApiConfig( $cfg ) {
		// 支付通知地址
		$config = DistributionShopPayLogic::getApiConfig( $this->cid, $cfg );
		$config['return_url'] = $config['notify_url'] = DistributionShopPayLogic::getCallBackUrl($cfg['paymentMethod'], $this->cid, null, null, $config['debug']*1);
		return $config;
	}
	
	/**
	 * 发送客服消息
	 * @param unknown $openId
	 * @param unknown $msg
	 */
	private function sendServerMsg( $openId, $data, $type = 0 ) {
		$accessToken = $this->wechatAdvance->getBaseAccess();
		$this->wechatAdvance->sendServerMessage( $accessToken['access_token'], $openId, $data, $type );
	}
	
	
	
	/**
	 * 报名支付
	 */
	public function payAction() {
		$aid = I('aid', 0, "intval");
		$payApi = "WxTenpay";
		if ( IS_AJAX ) {
			$success = "ajaxSuccess";
			$error = "ajaxError";
		} else {
			$success = "success";
			$error = "error";
		}
		// 活动信息
		$this->activity = M('WechatActivityInvite')->find($aid);
		 
		// 检查是否已经登记
		$this->rwSeparate(1);
		$invite = M('WechatActivityInviteRegister')->where(array(
				'cid' => $this->cid,
				'aid' => $aid,
				'openId' => $this->openId,
		))->find();
		$this->rwSeparate(0);
		 
		if ( $invite ) {
			$invite['pay'] and $this->$error("您已支付过了不要重复支付。");
			$invite['orderNo'] = DistributionShopOrderModel::randOrderNo($this->cid);
			M('WechatActivityInviteRegister')->save($invite);
		} else {
			$this->$error("还未报名，请先报名。");
		}
		 
		// 表单创建
		$formHtml = $this->createInviteForm( $invite, $this->activity, 'WxTenpay', IS_AJAX ? 1 : 0 );
	
		if ( IS_AJAX ) {
			$this->$success("$success", array('payForm'=> $formHtml));
		} else {
			header("Content-Type:text/html;charset=utf-8");
			exit( $formHtml );
		}
	}
	
	/**
	 * 报名支付表单创建
	 * @param unknown $invite
	 * @param string $payApi
	 * @return unknown
	 */
	private function createInviteForm( $invite, $activity, $payApi = 'WxTenpay', $isReady = 0 ) {
		/* 获得支付接口配置 */
		$apiConfig = DistributionShopPayLogic::getApiConfig($this->cid, array("paymentMethod" => $payApi));
		// 支付通知地址
		$apiConfig['notify_url'] = $apiConfig['return_url'] = U("Home/DisShopPay/notifyInvite", array('sid' => $this->cid, 'aid' => $activity['id'], 'apitype' => $payApi), false, true);
		// 系统附加参数
		$apiConfig['wparam'] = array(
				'backUrl' => U("Home/Invite/index", "cid={$this->cid}&aid={$activity['id']}"), // 支付成功后的返回页面
		);
	
		/* 获得支付接口 */
		$pay = \Utuo\Pay::getInstance($payApi, $apiConfig);
	
		/* 生成支付表单 */
		$vo = new \Utuo\Pay\PayVo();
		$vo->setTitle("到会报名");
		$vo->setBody("到会报名");
		$vo->setFee($activity['fee']);
		$vo->setOrderNo($invite['orderNo']);
		$vo->setParam(array(
				"isReady" => $isReady,
		));
		$formHtml = $pay->buildRequestForm( $vo );
		return $formHtml;
	}
	
	/**
	 * 报名支付回调
	 */
	public function notifyInviteAction() {
		$payApi = I('get.apitype', ''); // 获得支付方式
		$cid = $this->cid;
		$pay = \Utuo\Pay::getInstance($payApi, DistributionShopPayLogic::getApiConfig($cid, array("paymentMethod" => $payApi)));
		switch ($payApi) {
			case "WxTenpay":
				if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
					// 处理数据
					$notify = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);
					if( $pay->verifyNotify($notify) ) {
						$this->payInviteSuccess($notify["out_trade_no"]);
						exit("<xml><return_code>SUCCESS</return_code></xml>");
					} else {
						exit("<xml><return_code>FAIL</return_code></xml>");
					}
				} else {
					exit("<xml><return_code>FAIL</return_code></xml>");
				}
			default:
				exit("<xml><return_code>FAIL</return_code></xml>");
		}
	}
	
	/**
	 * 报名支付成功
	 */
	public function payInviteSuccess( $orderNo ) {
		M('WechatActivityInviteRegister')->where(array('orderNo' => $orderNo, ))->setField("pay", 1);
	}
	
}